package main;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import automaton.XmlAutomatonManager;

import utils.MyLogger;

import dataStructures.index.IdToRouteIndex;
import dataStructures.index.RouteToIdIndex;
import dk.brics.automaton.Automaton;

public class NodesSuggest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
	
		if (args.length != 1)
		{
			System.out.println("Usage <exe> <strategy file>");
			System.exit(-1);
		}
		
		NodesSuggestStrategy strategy = new NodesSuggestStrategy(args[0]);

		MyLogger logger = null;
		
		if (strategy.loggerPath != null)
		{
			logger = new MyLogger(strategy.loggerPath);
		}
		 
		new File(strategy.workingDirectory).mkdirs();
		 
		File indexFile = new File(strategy.workingDirectory, "index.idx");

		RouteToIdIndex routeIndex;
		IdToRouteIndex nodeIdIndex;
		
		if (!indexFile.exists())
		{
			//create new index and store it
			routeIndex = new RouteToIdIndex();
			//routeIndex.AttachLogger(logger);
			//routeIndex.LoadXml(strategy.xmlPath);
			//FileOutputStream fos = new FileOutputStream(indexFile.toString());
			//routeIndex.Store(fos);
			//fos.close();
			nodeIdIndex = new IdToRouteIndex();
			nodeIdIndex.LoadXml(strategy.xmlPath);
			FileOutputStream fos = new FileOutputStream(indexFile.toString());
			nodeIdIndex.Store(fos);
			fos.close();
		}
		else
		{
			//load stored index
			FileInputStream fos = new FileInputStream(indexFile.toString());
			routeIndex = RouteToIdIndex.Load(fos);
			fos.close();
		}
		System.out.println("Done!");
		System.exit(0);
		FileInputStream fos = new FileInputStream(indexFile.toString());
		nodeIdIndex = IdToRouteIndex.Load(fos);
		fos.close();
		
		
		XmlAutomatonManager automationManager = new XmlAutomatonManager(strategy.workingDirectory);
		
		
		if (!new File(strategy.workingDirectory, "automatons.map").exists())
		{
			//serialize path automations + mapping
			automationManager.AttachLogger(logger);
			automationManager.SerializeDocumentAutomatons(routeIndex);
		}
		
		//System.exit(0);
		//since there are few distinct paths (= automations) we need the mapping between every node to the serialized node which has
		//the same automaton as the node we are interesting in
		//HashMap<Integer, Integer> automationsMapping = automationManager.DeserializeAutomationMapping();

		System.out.println("here!!!");
		System.exit(0);
		//now, we need to intersect all positive (distinct) examples
		HashMap<Integer,Integer> usedPosIds = new HashMap<Integer, Integer>();
		
		HashMap<Integer,Integer> usedPositiveAutomatons = new HashMap<Integer, Integer>();
		
		Automaton posIntersectionAutomaton = null;
		
		for(int id : strategy.positiveExamples)
		{
			int representative = routeIndex.GetSerializedRouteNodesId(nodeIdIndex.GetRouteIndex(id)).get(0);//automationsMapping.get(id);
			usedPosIds.put(id, null);
			if (usedPositiveAutomatons.containsKey(representative))
			{
				continue;
			}
			else
			{
				if (posIntersectionAutomaton == null)
				{
					posIntersectionAutomaton = automationManager.DeserializeNodeAutomaton(representative);
				}
				else
				{
					posIntersectionAutomaton = posIntersectionAutomaton.intersection(automationManager.DeserializeNodeAutomaton(representative));
				}
				
				usedPositiveAutomatons.put(representative, null);
			}
		}
		
		HashMap<Integer,Integer> usedNegativeAutomatons = new HashMap<Integer, Integer>();
		
		ArrayList<Automaton> negExamplesAutomaton = new ArrayList<Automaton>();
		
		for(int id : strategy.negativeExamples)
		{
			int representative =  routeIndex.GetSerializedRouteNodesId(nodeIdIndex.GetRouteIndex(id)).get(0);//automationsMapping.get(id);
			//usedIds.put(id, null);
			if (usedPositiveAutomatons.containsKey(representative))
			{
				continue;
			}
			else
			{
				negExamplesAutomaton.add(automationManager.DeserializeNodeAutomaton(representative));
				usedNegativeAutomatons.put(representative, null);
			}
		}
		
		Automaton negUnionAutomaton = Automaton.union(negExamplesAutomaton);
		
		System.out.println(negUnionAutomaton.getFiniteStrings());
		System.out.println(posIntersectionAutomaton.getFiniteStrings());
		
		Automaton queryClassifier = posIntersectionAutomaton.intersection(negUnionAutomaton.complement());

		System.out.println(queryClassifier.getFiniteStrings());
		
		ArrayList<Integer> interestingNodesId = new ArrayList<Integer>();
		
		//go all over the nodes, add those which not in the pos or neg
		
		Iterator<ArrayList<Integer>> routesIter = routeIndex.RoutesIterator();
		
		System.out.println("Starting to go over groups");
		int groupNumber = 0;
 		while (routesIter.hasNext())
		{
 			groupNumber++;
 			ArrayList<Integer> serializedRoute = routesIter.next();
 			ArrayList<Integer> nodesId = routeIndex.GetSerializedRouteNodesId(serializedRoute);
  			int representative =  nodesId.get(0);//automationsMapping.get(nodesId.get(0));
			
   			Automaton A = automationManager.DeserializeNodeAutomaton(representative);

   			if (queryClassifier.intersection(A.complement()).isEmpty())
			{
				for(int id : nodesId)
				{
					if (!usedPosIds.containsKey(id))
					{
						interestingNodesId.add(id);
						System.out.println(id+1);
					}
				}
			}
		}
		
		
		
	}

}
